Technical Q&As


NW 28 - TCP Application Acquires Different Port Address After Relaunch (14-May-96)


Q In my Open Transport TCP based server application, I use a specific socket for receiving incoming connection requests.

If I relaunch the server immediately after quitting, the initialization calls complete without error, but the server never receives any incoming connection requests. If I wait several minutes before restarting the server, this problem doesn't occur. It appears that there is some internal timeout for disconnected connections. Is there a solution to this problem so that the server can be launched without waiting for the timeout?

A TCP has a 2-minute timeout on a binding after a connection has closed before the same port can be bound to again. This prevents stale data from corrupting a new connection. For this reason, you see a delay before you can successfully bind to the port again.

There is a way around this, using the IP_REUSEADDR option and the OTOptionManagement call. Set this option on all of your listening endpoints before you bind, and the problem should disappear.

Important - even after using the IP_REUSEADDR option, at most one endpoint that is in a state less than connected (listening; unbound doesn't count) may be bound to a given port. Any number of connected or closing endpoints may be so bound to other unique ports, however.

The following sample will help to show how to set this option. The function takes 2 input parameters, the EndpointRef that you want to set the option for, and the state of the option that you want, typically, true. The function returns a result of OSStatus. If the result is less than zero, then it it the result of making the OTOptionManagement call. If the result is positive, then the call completed successfully, but the status field had a value other than T_SUCCESS.

#include <OpenTransport.h>			// open transport files			
#include <OpenTptInternet.h>

/* input: noDelayState - true - nodelay
//						 false - normal delay state
//
// output:	if result less that kOTNoError, then the result of 
//		OTOptionManagement call is returned
//		otherwise, the status value is returned as defined in
//		OpenTransport.h
		T_SUCCESS	= 0x020,		return kOTNoError if SUCCESS
		T_FAILURE	= 0x040,
		T_PARTSUCCESS	= 0x100,
		T_READONLY	= 0x200,
		T_NOTSUPPORT	= 0x400
		
*/
OSStatus DoNegotiateIPReuseAddrOption(EndpointRef ep, Boolean reuseState)

{
	UInt8		buf[kOTFourByteOptionSize];	// define buffer for fourByte
							// Option size
	TOption*	opt;				// option ptr to make items
							// easier to access
	TOptMgmt	req;
	OSStatus	err;
	Boolean		isAsync = false;
	
	opt = (TOption*)buf;				// set option ptr to buffer
	req.opt.buf	= buf;
	req.opt.len	= sizeof(buf);
	req.opt.maxlen = sizeof(buf);			// were using ret for the
							// return result also.
	req.flags	= T_NEGOTIATE;			// negotiate for option


	opt->level	= INET_IP;			// dealing with an IP Level
							// function
	opt->name	= IP_REUSEADDR;
	opt->len	= kOTFourByteOptionSize;
	*(UInt32*)opt->value = reuseState;		// set the desired option
							// level, true or false

	if (OTIsSynchronous(ep) == false)		// check whether ep sync or
							// not
	{
		isAsync = true;			// set flag if async
		OTSetSynchronous(ep);			// set endpoint to sync	
	}
				
	err = OTOptionManagement(ep, &req, &req);
	
	if (isAsync == true)				// restore ep state if
							// necessary
		OTSetAsynchronous(ep);
		
		// if no error then check the option status value
	if (err == kOTNoError)
	{
		if (opt->status != T_SUCCESS) 	// if not T_SUCCESS, return
							// the status
			err = opt->status;
	}	// otherwise return kOTNOError

	return err;
}


Technical Q&As
Previous Question | Contents | Next Question